package nu.korkad.daytracker.io;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import nu.korkad.daytracker.R;
import nu.korkad.daytracker.database.DataHelper;
import nu.korkad.daytracker.info.Dates;
import nu.korkad.daytracker.settings.Config;
import nu.korkad.daytracker.settings.PrefStore;
import android.content.Context;

import com.dropbox.client2.DropboxAPI;
import com.dropbox.client2.android.AndroidAuthSession;
import com.dropbox.client2.exception.DropboxException;
import com.dropbox.client2.session.AccessTokenPair;
import com.dropbox.client2.session.AppKeyPair;

public class IO
{
    /**
     * Copies file src to dest.
     * 
     * @param src
     *            String
     * @param dest
     *            String
     * @param createdir
     *            boolean
     * @return String
     */
    public static String copy(String src, String dest, boolean createdir)
    {
        try
        {
            // Create dirs
            if (createdir)
                createExtDir();
            
            // Get streams
            InputStream in = new FileInputStream(new File(src));
            OutputStream out = new FileOutputStream(new File(dest));
            
            // Copy file to destination
            byte[] buf = new byte[1024];
            int len;
            while ((len = in.read(buf)) > 0)
                out.write(buf, 0, len);
            
            // Close files
            in.close();
            out.close();
            
            return "ok";
        }
        catch (IndexOutOfBoundsException e)
        {
            return e.getMessage();
        }
        catch (FileNotFoundException e)
        {
            return e.getMessage();
        }
        catch (IOException e)
        {
            return e.getMessage();
        }
    }
    
    /**
     * Creates the necessary external storage directories if needed.
     */
    public static void createExtDir()
    {
        // Create database dir
        File f1 = new File(Config.EXTERNAL_DIR_DATABASE);
        f1.mkdirs();
        
        // Create sharedpref dir
        File f2 = new File(Config.EXTERNAL_DIR_SHAREDPREF);
        f2.mkdirs();
        
        // Null them
        f1 = null;
        f2 = null;
    }
    
    /**
     * Creates internal files if needed.
     */
    public static void createIntFiles()
    {
        File f1 = new File(Config.INTERNAL_DIR_SHAREDPREF_GENERAL);
        
        // Check if sharedpref file exists
        if (!f1.exists())
            try
            {
                f1.createNewFile();
            }
            catch (IOException e)
            {
                Log.toExternal(e.getMessage());
            }
        
        // Null it
        f1 = null;
    }
    
    /**
     * Uploads files from internal storage to Dropbox.
     * 
     * @param context
     *            Context
     * @param mDBApi
     *            DropboxAPI
     * @return String
     */
    public static String toDropbox(Context context)
    {
        if (PrefStore.getDropboxKey(context).equals("") || PrefStore.getDropboxSecret(context).equals(""))
            return "";
        else
        {
            // Get dropbox stuff
            AppKeyPair appKeys = new AppKeyPair(Config.DROPBOX_APP_KEY, Config.DROPBOX_APP_SECRET);
            AndroidAuthSession session = new AndroidAuthSession(appKeys, Config.DROPBOX_ACCESS_TYPE);
            DropboxAPI<AndroidAuthSession> mDBApi = new DropboxAPI<AndroidAuthSession>(session);
            AccessTokenPair access = new AccessTokenPair(PrefStore.getDropboxKey(context), PrefStore.getDropboxSecret(context));
            mDBApi.getSession().setAccessTokenPair(access);
            
            try
            {
                // Create internal files if necessary
                IO.createIntFiles();
                
                // Get files
                File database = new File(Config.INTERNAL_DIR_DATABASE_FILE);
                File spGeneral = new File(Config.INTERNAL_DIR_SHAREDPREF_GENERAL);
                
                // Send files to dropbox
                if (database.exists())
                    mDBApi.putFileOverwrite("/" + Config.DROPBOX_DEVICE_ID + Config.DROPBOX_DIR_DATABASE_FILE,
                            new FileInputStream(database), database.length(), null);
                if (spGeneral.exists())
                    mDBApi.putFileOverwrite("/" + Config.DROPBOX_DEVICE_ID + Config.DROPBOX_DIR_SHAREDPREF_GENERAL, new FileInputStream(
                            spGeneral), spGeneral.length(), null);
                
                // Null files
                database = null;
                spGeneral = null;
                
                return "dropbox";
            }
            catch (FileNotFoundException e)
            {
                System.out.println("fnf: " + e.getMessage());
                return e.getMessage();
            }
            catch (DropboxException e)
            {
                System.out.println("a " + e.getMessage());
                return e.getMessage();
            }
        }
    }
    
    /**
     * Copies file from internal storage to external storage.
     * 
     * @return String
     */
    public static String toExternal()
    {
        // Create internal files if necessary
        IO.createIntFiles();
        
        // Copy files and get their messages
        String temp1 = IO.copy(Config.INTERNAL_DIR_DATABASE_FILE, Config.EXTERNAL_DIR_DATABASE_FILE, true);
        String temp2 = IO.copy(Config.INTERNAL_DIR_SHAREDPREF_GENERAL, Config.EXTERNAL_DIR_SHAREDPREF_GENERAL, true);
        
        // Put them in String array
        String[] messages = new String[] { temp1, temp2 };
        
        // Null temp strings
        temp1 = null;
        temp2 = null;
        
        // Loop through string array to find error messages
        for (String n : messages)
            if (!n.equals("ok"))
                return n;
        
        // Everything was ok, return
        return "external";
    }
    
    /**
     * Copies files from external storage to internal storage.
     * 
     * @return String
     */
    public static String fromExternal()
    {
        // Copy files and get their messages
        String temp1 = IO.copy(Config.EXTERNAL_DIR_DATABASE_FILE, Config.INTERNAL_DIR_DATABASE_FILE, false);
        String temp2 = IO.copy(Config.EXTERNAL_DIR_SHAREDPREF_GENERAL, Config.INTERNAL_DIR_SHAREDPREF_GENERAL, false);
        
        // Put them in String array
        String[] messages = new String[] { temp1, temp2 };
        
        // Null temp strings
        temp1 = null;
        temp2 = null;
        
        // Loop through string array to find error messages
        for (String n : messages)
            if (!n.equals("ok"))
                return n;
        
        // Everything was ok, return
        return "external";
    }
    
    /**
     * Retrieves necessary info from db and then passes it on to exportReportToDropbox.
     * 
     * @param id
     *            int
     * @param dh
     *            DataHelper
     * @param context
     *            Context
     * @param mDBApi
     *            DropboxAPI
     * @return ""
     */
    public static String exportReportToDropbox(int id, DataHelper dh, Context context, DropboxAPI<AndroidAuthSession> mDBApi)
    {
        // Get info from db
        String[] info = dh.getInfo(id);
        
        // Send info to function
        exportReportToDropbox(info[3], info[0], Integer.toString(id), Long.parseLong(info[1]), Long.parseLong(info[2]),
                new File(context.getCacheDir() + File.separator + id + ".txt"), context, mDBApi);
        
        return "";
    }
    
    /**
     * Puts all the variables together to build a report looking like the detailed info in archive activity and then uploads it to Dropbox
     * in txt format.
     * 
     * @param text
     *            String
     * @param companyName
     *            String
     * @param id
     *            String
     * @param checkin
     *            Long
     * @param checkout
     *            Long
     * @param filename
     *            String
     * @param context
     *            Context
     * @return ""
     */
    public static String exportReportToDropbox(final String text, final String companyName, final String id, final Long checkin,
            final Long checkout, final File filename, final Context context, final DropboxAPI<AndroidAuthSession> mDBApi)
    {
        new Thread(new Runnable()
        {
            @Override
            public void run()
            {
                try
                {
                    // Verify accesstokens
                    if (PrefStore.getDropboxKey(context).equals("") || PrefStore.getDropboxSecret(context).equals(""))
                        System.out.println("Missing dropbox keys");
                    else
                    {
                        // Open filewriter
                        FileWriter file = new FileWriter(filename);
                        
                        // Write to file
                        file.write(context.getString(R.string.dialog_archive_text_id) + " " + id + "\n"
                                + context.getString(R.string.dialog_archive_text_company) + " " + companyName + "\n"
                                + context.getString(R.string.dialog_archive_text_checkin) + " " + Dates.getArchiveDate(checkin, context)
                                + "\n" + context.getString(R.string.dialog_archive_text_checkout) + " "
                                + Dates.getArchiveDate(checkout, context) + "\n" + context.getString(R.string.dialog_archive_text_duration)
                                + " " + Dates.getDuration(checkin * 1000, checkout * 1000, context) + "\n\n"
                                + context.getString(R.string.dialog_archive_text_report) + "\n" + text);
                        
                        // Close file
                        file.close();
                        
                        // Get dropbox keys
                        AccessTokenPair access = new AccessTokenPair(PrefStore.getDropboxKey(context), PrefStore.getDropboxSecret(context));
                        mDBApi.getSession().setAccessTokenPair(access);
                        
                        // Send file to dropbox
                        mDBApi.putFileOverwrite("/" + Config.DROPBOX_DEVICE_ID + Config.DROPBOX_DIR_REPORTS + id + ".txt",
                                new FileInputStream(filename), filename.length(), null);
                    }
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
                catch (DropboxException e)
                {
                    e.printStackTrace();
                }
                finally
                {
                    // Delete temp file
                    if (filename.exists())
                        filename.delete();
                }
            }
        }, "dropbox io").start();
        
        return "";
    }
}
